#region License

// Copyright 2007-2008 Rory Plaire (codekaizen@gmail.com)
/*
 * This license governs use of the accompanying software. If you use the software, you
 * accept this license. If you do not accept the license, do not use the software.
 *
 * 1. Definitions
 * The terms "reproduce," "reproduction," "derivative works," and "distribution" have the
 * same meaning here as under U.S. copyright law.
 * A "contribution" is the original software, or any additions or changes to the software.
 * A "contributor" is any person that distributes its contribution under this license.
 * "Licensed patents" are a contributor's patent claims that read directly on its contribution.
 *
 * 2. Grant of Rights
 * (A) Copyright Grant- Subject to the terms of this license, including the license conditions
 *     and limitations in section 3, each contributor grants you a non-exclusive, worldwide,
 *     royalty-free copyright license to reproduce its contribution, prepare derivative works
 *     of its contribution, and distribute its contribution or any derivative works that you create.
 * (B) Patent Grant- Subject to the terms of this license, including the license conditions and
 *     limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free
 *     license under its licensed patents to make, have made, use, sell, offer for sale, import,
 *     and/or otherwise dispose of its contribution in the software or derivative works of the
 *     contribution in the software.
 *
 * 3. Conditions and Limitations
 * (A) No Trademark License- This license does not grant you rights to use any contributors'
 *     name, logo, or trademarks.
 * (B) If you bring a patent claim against any contributor over patents that you claim are
 *     infringed by the software, your patent license from such contributor to the software
 *     ends automatically.
 * (C) If you distribute any portion of the software, you must retain all copyright, patent,
 *     trademark, and attribution notices that are present in the software.
 * (D) If you distribute any portion of the software in source code form, you may do so only under
 *     this license by including a complete copy of this license with your distribution. If you
 *     distribute any portion of the software in compiled or object code form, you may only do so
 *     under a license that complies with this license.
 * (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no
 *     express warranties, guarantees or conditions. You may have additional consumer rights under
 *     your local laws which this license cannot change. To the extent permitted under your local laws,
 *     the contributors exclude the implied warranties of merchantability, fitness for a particular
 *     purpose and non-infringement.
 *
 */

#endregion License

// Based initially on JAMA : A Java Matrix Package by
// National Institute of Standards and Technology (NIST)
// and The MathWorks, a public-domain work.

using System;
using NPack.Interfaces;

namespace NPack
{
    internal static class Utility
    {
        public static T Hypotenuse<T>(T a, T b)
            where T : IComputable<T>, IHasZero<T>
        {
            var aAbs = a.Abs();
            var bAbs = b.Abs();
            if (aAbs.GreaterThan(bAbs))
            {
                var r = b.Divide(a);
                return aAbs.Multiply((r.Multiply(r).Add(a.One)).Sqrt());
            }

            if (!b.Equals(b.Zero))
            {
                var r = a.Divide(b);
                return bAbs.Multiply((r.Multiply(r).Add(b.One)).Sqrt());
            }

            return a.Zero;
        }

        public static T Max<T>(T value1, T value2)
            where T : IBooleanComparable<T>
        {
            return value1.GreaterThanOrEqualTo(value2)
                ? value1
                : value2;
        }

        public static T Min<T>(T value1, T value2)
            where T : IBooleanComparable<T>
        {
            return value1.LessThanOrEqualTo(value2)
                ? value1
                : value2;
        }

        public static T New<T>(Int32 value)
            where T : IComputable<T>
        {
            var r = default(T);
            return r.Set(value);
        }

        public static T New<T>(Double value)
            where T : IComputable<T>
        {
            var r = default(T);
            return r.Set(value);
        }

        public static T New<T>(Single value)
        where T : IComputable<T>
        {
            var r = default(T);
            return r.Set(value);
        }
    }
}